#include "video_svr.h"

#define CVTQT(x) (x == 0 ? 10 : (x == 1 ? 20 : (x == 2 ? 30 : (x == 3 ? 40 : 50))))

CVideo_svr::CVideo_svr(LPST_ENV_T pEnv)
: m_pEnv(pEnv)
, m_thread_id(NULL)
{
	int i;
	LOG4CPLUS_DEBUG(log_dsw, "Create video server!");
	for (i = 0; i < m_pEnv->nMaxChannel; i++){
		int nChId = i;
		void* pParam = (void*)(&nChId);
		pEnv->pOnNotifyFunc(PMSG_GET_VIDEOINFO, pParam);
		m_pChParam[i] = (LPST_CH_PARAM)pParam;

		pthread_mutex_init(&m_alarm_list[i].nLock, NULL);
	}

	StartMainSubStream();
}

CVideo_svr::~CVideo_svr()
{
	StopMainSunStream();

	for (int i = 0; i < m_pEnv->nMaxChannel; i++){
		while(!m_alarm_list[i].nAlarmList.empty()){
			LPST_ALARM_MSG_T pNode = m_alarm_list[i].nAlarmList.front();
			m_alarm_list[i].nAlarmList.pop_front();
			delete pNode;
		}
		pthread_mutex_destroy(&m_alarm_list[i].nLock);
	}
	
	LOG4CPLUS_DEBUG(log_dsw, "Destroy video server!");
}

void CVideo_svr::StartMainSubStream()
{
	m_groupfd = gm_new_groupfd();
	int nCh;
	for (nCh = 0; nCh < m_pEnv->nMaxChannel; nCh++){
		pthread_mutex_init(&m_video_mem[nCh][MAIN_STREAM].lock, NULL);
		pthread_mutex_init(&m_video_mem[nCh][SUB_STREAM].lock, NULL);
		m_video_mem[nCh][MAIN_STREAM].seq = m_video_mem[nCh][SUB_STREAM].seq = 0;
		
		DECLARE_ATTR(cap_attr, gm_cap_attr_t);
		DECLARE_ATTR(h264e_attr, gm_h264e_attr_t);
		DECLARE_ATTR(cap_3di_attr, gm_3di_attr_t);

		m_capture_object[nCh] = gm_new_obj(GM_CAP_OBJECT);
		m_main_enc_object[nCh] = gm_new_obj(GM_ENCODER_OBJECT);
		m_sub_enc_object[nCh] = gm_new_obj(GM_ENCODER_OBJECT);

		/*** Init mainstream */
		cap_attr.cap_vch = nCh;
		cap_attr.path = GM_MAINSUBSTREAM;
		cap_attr.enable_mv_data = 0;
		gm_set_attr(m_capture_object[nCh], &cap_attr);

		cap_3di_attr.deinterlace = 1;
		cap_3di_attr.denoise = 1;
		gm_set_attr(m_capture_object[nCh], &cap_3di_attr);

		h264e_attr.dim.width = MAKE_V_WIDTH(m_pChParam[nCh]->vtype, m_pChParam[nCh]->bs[MAIN_STREAM].size);//pEnv->gm_system.cap[nCh].dim.width;
		h264e_attr.dim.height = MAKE_V_HEIGHT(m_pChParam[nCh]->vtype, m_pChParam[nCh]->bs[MAIN_STREAM].size);//pEnv->gm_system.cap[nCh].dim.height;
		h264e_attr.frame_info.framerate = m_pChParam[nCh]->bs[MAIN_STREAM].fps;//pEnv->gm_system.cap[nCh].framerate;
		h264e_attr.ratectl.mode = GM_EVBR;//GM_CBR;
		h264e_attr.ratectl.gop = m_pChParam[nCh]->bs[MAIN_STREAM].gop;//60;
//		h264e_attr.ratectl.bitrate_max = h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps;//2048;  // 2Mbps
//		h264e_attr.ratectl.init_quant = CVTQT(m_pChParam[nCh]->bs[MAIN_STREAM].quality);
//		h264e_attr.ratectl.min_quant = 1;
//		h264e_attr.ratectl.max_quant = 51;
		switch(m_pChParam[nCh]->bs[MAIN_STREAM].quality){
		case 0:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps;
			break;
		case 1:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps * 0.8;
			break;
		case 2:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps * 0.7;
			break;
		case 3:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps * 0.5;
			break;
		default:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[MAIN_STREAM].bps * 0.2;
			break;		
		}
		h264e_attr.ratectl.bitrate_max = m_pChParam[nCh]->bs[MAIN_STREAM].bps;

		h264e_attr.b_frame_num = 0; // B-frames per GOP (H.264 high profile)
		h264e_attr.enable_mv_data = 0;  // disable H.264 motion data output
		gm_set_attr(m_main_enc_object[nCh], &h264e_attr);

		m_main_bindfd[nCh] = gm_bind(m_groupfd, m_capture_object[nCh], m_main_enc_object[nCh]);

		/*** Init substream */
		h264e_attr.dim.width = MAKE_V_WIDTH(m_pChParam[nCh]->vtype, m_pChParam[nCh]->bs[SUB_STREAM].size);//pEnv->gm_system.cap[nCh].dim.width / 2;
		h264e_attr.dim.height = MAKE_V_HEIGHT(m_pChParam[nCh]->vtype, m_pChParam[nCh]->bs[SUB_STREAM].size);//pEnv->gm_system.cap[nCh].dim.height / 2;
		h264e_attr.frame_info.framerate = m_pChParam[nCh]->bs[SUB_STREAM].fps;//pEnv->gm_system.cap[nCh].framerate;

		switch(m_pChParam[nCh]->bs[SUB_STREAM].quality){
		case 0:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps;
			break;
		case 1:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps * 0.8;
			break;
		case 2:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps * 0.7;
			break;
		case 3:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps * 0.5;
			break;
		default:
			h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps * 0.2;
			break;		
		}
		h264e_attr.ratectl.bitrate_max = m_pChParam[nCh]->bs[SUB_STREAM].bps;
//		h264e_attr.ratectl.bitrate_max = h264e_attr.ratectl.bitrate = m_pChParam[nCh]->bs[SUB_STREAM].bps;//512;
//		h264e_attr.ratectl.init_quant = CVTQT(m_pChParam[nCh]->bs[SUB_STREAM].quality);
		gm_set_attr(m_sub_enc_object[nCh], &h264e_attr);

		m_sub_bindfd[nCh] = gm_bind(m_groupfd, m_capture_object[nCh], m_sub_enc_object[nCh]);
		
		if (gm_apply(m_groupfd) < 0){
			LOG4CPLUS_ERROR(log_dsw, "gm_apply fail, AP procedure something wrong!");
		}

		m_pOsd[nCh] = new CDswosd(m_pEnv, m_capture_object[nCh], nCh);
	}
	
	pthread_create(&m_thread_id, NULL, CVideo_svr::cbThreadFunc, (void *)this);
}

void CVideo_svr::StopMainSunStream()
{
	if (m_thread_id)
		pthread_join(m_thread_id, NULL);
	int i;
	for (i = 0; i < m_pEnv->nMaxChannel; i++){
		if (m_pOsd[i])
			delete m_pOsd[i];
		gm_unbind(m_main_bindfd[i]);
		gm_unbind(m_sub_bindfd[i]);
		gm_apply(m_groupfd);
		gm_delete_obj(m_main_enc_object[i]);
		gm_delete_obj(m_sub_enc_object[i]);
		gm_delete_obj(m_capture_object[i]);
	}
	gm_delete_groupfd(m_groupfd);

	for (i = 0; i < m_pEnv->nMaxChannel; i++){
		while(!m_video_mem[i][MAIN_STREAM].vlist.empty()){
			LPST_VIDEO_FRAME_T pNode = m_video_mem[i][MAIN_STREAM].vlist.front();
			m_video_mem[i][MAIN_STREAM].vlist.pop_front();
			if (pNode->pFrame != NULL)
				delete pNode->pFrame;
			delete pNode;
		}
		while(!m_video_mem[i][SUB_STREAM].vlist.empty()){
			LPST_VIDEO_FRAME_T pNode = m_video_mem[i][SUB_STREAM].vlist.front();
			m_video_mem[i][SUB_STREAM].vlist.pop_front();
			if (pNode->pFrame != NULL)
				delete pNode->pFrame;
			delete pNode;
		}
		pthread_mutex_destroy(&m_video_mem[i][MAIN_STREAM].lock);
		pthread_mutex_destroy(&m_video_mem[i][SUB_STREAM].lock);
	}
}

void CVideo_svr::EncThreadFunc()
{
	LOG4CPLUS_DEBUG(log_dsw, "Start Video encode thread!");
	char *bitstream_data[MAX_CHANNEL][MAX_V_BITSTREAM_NUM];
	int bitstream_datalen[MAX_CHANNEL][MAX_V_BITSTREAM_NUM];
	gm_pollfd_t poll_fds[MAX_CHANNEL * MAX_V_BITSTREAM_NUM];
	gm_enc_multi_bitstream_t multi_bs[MAX_CHANNEL * MAX_V_BITSTREAM_NUM];
	int i, j, ret;

	pthread_t nCapturePicThread;

	pthread_create(&nCapturePicThread, NULL, CVideo_svr::cbCapturePICThreadFunc, (void *)this);

	for (j = 0; j < m_pEnv->nMaxChannel; j++){
		for (i = 0; i < MAX_V_BITSTREAM_NUM; i++){
			bitstream_data[j][i] = NULL;
			bitstream_datalen[j][i] = 0;
		}
	}

	memset(poll_fds, 0, sizeof(poll_fds));

	for (j = 0; j < m_pEnv->nMaxChannel; j++){
		/*** Capture mainstream stream */
		poll_fds[j * MAX_V_BITSTREAM_NUM + MAIN_STREAM].bindfd = m_main_bindfd[j];
		poll_fds[j * MAX_V_BITSTREAM_NUM + MAIN_STREAM].event = GM_POLL_READ;
		/*** Capture another path substream */
		poll_fds[j * MAX_V_BITSTREAM_NUM + SUB_STREAM].bindfd = m_sub_bindfd[j];
		poll_fds[j * MAX_V_BITSTREAM_NUM + SUB_STREAM].event = GM_POLL_READ;
	}

	while(!m_pEnv->bExit){
		ret = gm_poll(poll_fds, MAX_V_BITSTREAM_NUM * m_pEnv->nMaxChannel, 500);
		if (ret == GM_TIMEOUT) {
			LOG4CPLUS_WARN(log_dsw, "Poll video timeout!!");
			continue;
		}
		memset(multi_bs, 0, sizeof(multi_bs));
#if 1
		for (j = 0; j < m_pEnv->nMaxChannel; j++){
			for (i = 0; i < MAX_V_BITSTREAM_NUM; i++) {
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.event != GM_POLL_READ)
					continue;
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len > V_BITSTREAM_LEN) {
					LOG4CPLUS_ERROR(log_dsw, "bitstream buffer length is not enough!" << poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len << ", " << V_BITSTREAM_LEN);
					continue;
				}
				multi_bs[j * MAX_V_BITSTREAM_NUM + i].bindfd = poll_fds[j * MAX_V_BITSTREAM_NUM + i].bindfd;
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len > bitstream_datalen[j][i]){
					if (bitstream_data[j][i] != NULL)
						delete bitstream_data[j][i];
					bitstream_data[j][i] = new char[poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len + (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len % sizeof(int))];
					bitstream_datalen[j][i] = poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len;
				}
				multi_bs[j * MAX_V_BITSTREAM_NUM + i].bs.bs_buf = bitstream_data[j][i];
				multi_bs[j * MAX_V_BITSTREAM_NUM + i].bs.bs_buf_len = bitstream_datalen[j][i];//poll_fds[i].revent.bs_len;
				multi_bs[j * MAX_V_BITSTREAM_NUM + i].bs.mv_buf = 0;
				multi_bs[j * MAX_V_BITSTREAM_NUM + i].bs.mv_buf_len = 0;
			}
		}
		if ((ret = gm_recv_multi_bitstreams(multi_bs, MAX_V_BITSTREAM_NUM * m_pEnv->nMaxChannel)) < 0) {
			LOG4CPLUS_ERROR(log_dsw, "Error return value! value = " << ret);
		}
		else {
			for (j = 0; j < m_pEnv->nMaxChannel; j++){
				for (i = 0; i < MAX_V_BITSTREAM_NUM; i++) {
					if ((multi_bs[j * MAX_V_BITSTREAM_NUM + i].retval < 0) && multi_bs[j * MAX_V_BITSTREAM_NUM + i].bindfd) {
						LOG4CPLUS_ERROR(log_dsw, "CH[" << j << "] streams [" << i << "] Error to receive bitstream. ret = " << multi_bs[j * MAX_V_BITSTREAM_NUM + i].retval);
					}
					else if (multi_bs[j * MAX_V_BITSTREAM_NUM + i].retval == GM_SUCCESS) {
						PutFrameToMem(j, i, &(multi_bs[j * MAX_V_BITSTREAM_NUM + i].bs));
					}
				}
			}
		}
#else
		int nPolled = 0;
		int nPolledCh[MAX_CHANNEL] = {0};
		
		for (j = 0; j < MAX_CHANNEL; j++){
			for (i = 0; i < MAX_V_BITSTREAM_NUM; i++) {
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.event != GM_POLL_READ)
					continue;
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len > V_BITSTREAM_LEN) {
					LOG4CPLUS_ERROR(log_dsw, "bitstream buffer length is not enough!" << poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len << ", " << V_BITSTREAM_LEN);
					continue;
				}
				multi_bs[nPolled].bindfd = poll_fds[j * MAX_V_BITSTREAM_NUM + i].bindfd;
				if (poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len > bitstream_datalen[j][i]){
					if (bitstream_data[j][i] != NULL)
						delete bitstream_data[j][i];
					bitstream_data[j][i] = new char[poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len];
					bitstream_datalen[j][i] = poll_fds[j * MAX_V_BITSTREAM_NUM + i].revent.bs_len;
				}
				multi_bs[nPolled].bs.bs_buf = bitstream_data[j][i];
				multi_bs[nPolled].bs.bs_buf_len = bitstream_datalen[j][i];//poll_fds[i].revent.bs_len;
				multi_bs[nPolled].bs.mv_buf = 0;
				multi_bs[nPolled].bs.mv_buf_len = 0;
				nPolledCh[nPolled] = ((j << 8) | i);
				nPolled++;
			}
		}
		if (nPolled == 0)
			continue;
		if ((ret = gm_recv_multi_bitstreams(multi_bs, nPolled)) < 0) {
			LOG4CPLUS_ERROR(log_dsw, "Error return value! value = " << ret);
		}
		else {
			for (i = 0; i < nPolled; i++){
				if ((multi_bs[i].retval < 0) && multi_bs[i].bindfd) {
					LOG4CPLUS_ERROR(log_dsw, "CH[" << (nPolledCh[nPolled] >> 8) << "] streams [" << (nPolledCh[nPolled] & 0xff) << "] Error to receive bitstream. ret = " << multi_bs[i].retval);
				}
				else if (multi_bs[i].retval == GM_SUCCESS) {
					PutFrameToMem((nPolledCh[nPolled] >> 8), (nPolledCh[nPolled] & 0xff), &(multi_bs[i].bs));
				}
			}
		}
#endif
	}
	for (j = 0; j < m_pEnv->nMaxChannel; j++){
		for (i = 0; i < MAX_V_BITSTREAM_NUM; i++){
			if (bitstream_data[j][i] != NULL)
				free(bitstream_data[j][i]);
		}
	}

	if (nCapturePicThread)
		pthread_join(nCapturePicThread, NULL);

	LOG4CPLUS_DEBUG(log_dsw, "Exit Video encode thread!");
}

void CVideo_svr::PutFrameToMem(int nCh, int nStreamID, gm_enc_bitstream_t *pBs)
{
	pthread_mutex_lock(&m_video_mem[nCh][nStreamID].lock);
	LPST_VIDEO_FRAME_T pNode;
	if (m_video_mem[nCh][nStreamID].vlist.size() < MAX_FRAMES){
		pNode = new ST_VIDEO_FRAME_T;
		pNode->pFrame = new unsigned char[pBs->bs_len + (pBs->bs_len % sizeof(int))];
		pNode->bufsize = pBs->bs_len;
	}
	else{
		pNode = m_video_mem[nCh][nStreamID].vlist.front();
		m_video_mem[nCh][nStreamID].vlist.pop_front();
		if (pNode->bufsize < pBs->bs_len){
			delete pNode->pFrame;
			pNode->pFrame = new unsigned char[pBs->bs_len + (pBs->bs_len % sizeof(int))];
			pNode->bufsize = pBs->bs_len;
		}
	}
	pNode->ch_num = nCh;
	pNode->sub_num = nStreamID;
	pNode->is_newbs = (pBs->newbs_flag != 0);
	pNode->is_keyframe = (pBs->keyframe == 1);
	pNode->seq = m_video_mem[nCh][nStreamID].seq++;
	pNode->length = pBs->bs_len;
	memcpy(pNode->pFrame, pBs->bs_buf, pBs->bs_len);
	gettimeofday(&pNode->timestamp, NULL);
	m_video_mem[nCh][nStreamID].vlist.push_back(pNode);
	pthread_mutex_unlock(&m_video_mem[nCh][nStreamID].lock);
}

void CVideo_svr::GetFrameFromMem(int nCh, LPST_VIDEO_FRAME_T pFrame)
{
	bool bHaveFrame = false;
	int nstream = pFrame->sub_num;
	unsigned int nseq = pFrame->seq;
	pthread_mutex_t* pmutex = &(m_video_mem[nCh][nstream].lock);
	LIST_VIDEO_MEM_T* plist = &(m_video_mem[nCh][nstream].vlist);

	pFrame->length = -1;
	pthread_mutex_lock(pmutex);
	if (plist->empty()){
		pthread_mutex_unlock(pmutex);
		return;
	}
	LIST_VIDEO_MEM_T::iterator it;
	for (it = plist->begin(); it != plist->end(); it++){
		if ((*it)->seq >= nseq){
			if ((nseq == 0) && !(*it)->is_keyframe){
				continue;
			}
			if ((*it)->length > pFrame->bufsize){
				if (pFrame->pFrame != NULL)
					delete pFrame->pFrame;
				pFrame->pFrame = new unsigned char[(*it)->length + ((*it)->length % sizeof(int))];
				memcpy(pFrame, (*it), sizeof(ST_VIDEO_FRAME_T) - sizeof(unsigned char*));
				pFrame->bufsize = (*it)->length;
			}
			else{
				int nsize = pFrame->bufsize;
				memcpy(pFrame, (*it), sizeof(ST_VIDEO_FRAME_T) - sizeof(unsigned char*));
				pFrame->bufsize = nsize;
			}
			memcpy(pFrame->pFrame, (*it)->pFrame, (*it)->length);
			bHaveFrame = true;
			break;
		}
		else if ((*it)->seq == 0){
//			printf("jjjjjjjjjjjjjjjj = %x, %x, %d\n", (*it)->seq, nseq, nCh);
		}
	}
	if ((nseq == 0) && !bHaveFrame)
		gm_request_keyframe((nstream == MAIN_STREAM) ? m_main_bindfd[nCh] : m_sub_bindfd[nCh]);
	pthread_mutex_unlock(pmutex);
}

void CVideo_svr::SetCapturePIC(int nCh, unsigned int nAreId, unsigned int nTrigVal, time_t nTrigTime, unsigned int nAction)
{
	pthread_mutex_lock(&m_alarm_list[nCh].nLock);
	if (m_alarm_list[nCh].nAlarmList.size() < MAX_ALARM_PROCESS_NODE){
		LPST_ALARM_MSG_T pNode = new ST_ALARM_MSG_T;
		pNode->nAreId = nAreId;
		pNode->nTrigVal = nTrigVal;
		pNode->nAlarmTime = nTrigTime;
		pNode->nAction = nAction;
		m_alarm_list[nCh].nAlarmList.push_back(pNode);
	}
	else
		LOG4CPLUS_WARN(log_dsw, "Ch [ " << nCh<< " ] too many alarm to process! drop this pic cap alarm!");
	pthread_mutex_unlock(&m_alarm_list[nCh].nLock);
}

void CVideo_svr::CapturePICThreadFunc()
{
	LOG4CPLUS_DEBUG(log_dsw, "Begin pic capture thread!");
	while(!m_pEnv->bExit){
		int i;
		for (i = 0; i < m_pEnv->nMaxChannel; i++){
			pthread_mutex_lock(&m_alarm_list[i].nLock);
			if (m_alarm_list[i].nAlarmList.empty()){
				pthread_mutex_unlock(&m_alarm_list[i].nLock);
				usleep(1000 * 10);
				continue;
			}
			LPST_ALARM_MSG_T pNode = m_alarm_list[i].nAlarmList.front();
			m_alarm_list[i].nAlarmList.pop_front();

			bool bGprsMode;
			void* pParam = (void*)&bGprsMode;
			m_pEnv->pOnNotifyFunc(PMSG_GET_ISGPRS, pParam);
		
			snapshot_t snapshot;
			char* snapshot_buf = new char[MAX_SNAPHSOT_LEN];
			snapshot.bs_buf = snapshot_buf;
			snapshot.bs_buf_len = MAX_SNAPHSOT_LEN;
			if (!bGprsMode){
				snapshot.image_quality = 70;
				snapshot.bindfd = m_main_bindfd[i];
				snapshot.bs_width = MAKE_V_WIDTH(m_pChParam[i]->vtype, m_pChParam[i]->bs[MAIN_STREAM].size);
				snapshot.bs_height =  MAKE_V_HEIGHT(m_pChParam[i]->vtype, m_pChParam[i]->bs[MAIN_STREAM].size);
			}
			else{
				snapshot.image_quality = 35;
				snapshot.bindfd = m_sub_bindfd[i];
				snapshot.bs_width = MAKE_V_WIDTH(m_pChParam[i]->vtype, m_pChParam[i]->bs[SUB_STREAM].size);
				snapshot.bs_height =  MAKE_V_HEIGHT(m_pChParam[i]->vtype, m_pChParam[i]->bs[SUB_STREAM].size);
			}
			int snapshot_len = gm_request_snapshot(&snapshot, 500);
//			int snapshot_len = -1;
			if (snapshot_len > 0){
				ST_CAPTURE_RESULT_T nResult;
				nResult.nAlarmTime = pNode->nAlarmTime;
				nResult.nAreId = pNode->nAreId;
				nResult.nPayloadType = EN_PIC;
				nResult.nPayloadSize = snapshot_len;
				nResult.nTrigVal = pNode->nTrigVal;
				nResult.pPic = snapshot_buf;
				nResult.nBindV = i;
				nResult.bNeedPtz = ((pNode->nAction & EN_VIDEO) ? false : true);
				void* pParam = (void*)&nResult;
				m_pEnv->pOnNotifyFunc(PMSG_SET_CAPTURE_RESULT, pParam);
				LOG4CPLUS_DEBUG(log_dsw, "Ch[ " << i << " ] capture pic ok!");
			}
			else{
				LOG4CPLUS_ERROR(log_dsw, "Ch[ " << i << " ] capture pic failed!");
				delete snapshot_buf;
			}

			delete pNode;
			pthread_mutex_unlock(&m_alarm_list[i].nLock);
		}
	}
	LOG4CPLUS_DEBUG(log_dsw, "Exit pic capture thread!");
}


